from rest_framework import serializers
from goods.models import SKU, GoodsCategory, SPU, SPUSpecification, SpecificationOption, SKUSpecification
from django.db import transaction


# 0,SKUSpecification序列化器
class SKUSpecificationSerializer(serializers.Serializer):
    spec_id = serializers.IntegerField()  # 匹配 spec
    option_id = serializers.IntegerField()  # 匹配 option


# 1,sku序列化器
class SKUViewSetSerializer(serializers.ModelSerializer):
    # 1,重写分类
    category = serializers.StringRelatedField(read_only=True)
    category_id = serializers.IntegerField()

    # 2,spu重写
    spu = serializers.StringRelatedField(read_only=True)
    spu_id = serializers.IntegerField()

    # 3,specs重写
    specs = SKUSpecificationSerializer(read_only=True, many=True)

    class Meta:
        model = SKU
        fields = "__all__"

    # 3,重写create方法，保存sku和对应的规格
    @transaction.atomic
    def create(self, validated_data):

        # TODO 设置保存点
        sid = transaction.savepoint()

        try:
            # 1,创建sku对象入库
            sku = SKU.objects.create(**validated_data)  # 固定格式

            # 2,创建格式信息入库
            specs = self.context['request'].data['specs']  # 取前端带过来的数据，固定格式
            for spec_dict in specs:
                SKUSpecification.objects.create(sku_id=sku.id, spec_id=spec_dict["spec_id"],
                                                option_id=spec_dict["option_id"])
        except Exception as e:
            transaction.savepoint_rollback(sid)  # TODO 回滚
            raise serializers.ValidationError("保存失败")
        else:
            # 3,返回响应,
            transaction.savepoint_commit(sid)  # TODO 提交
            return sku

    # 4,重写update方法,更新sku中的规格
    @transaction.atomic
    def update(self, instance, validated_data):

        # TODO 设置保存点
        sid = transaction.savepoint()

        try:
            # 1,更新sku其他信息(标题,价格,...)
            SKU.objects.filter(id=instance.id).update(**validated_data)

            # 2,更新规格信息入库
            specs = self.context["request"].data["specs"]
            for spec_dict in specs:
                SKUSpecification.objects.filter(sku_id=instance.id, spec_id=spec_dict['spec_id']).update(
                    option_id=spec_dict["option_id"])
        except Exception as e:
            transaction.savepoint_rollback(sid)  # TODO 回滚
            raise serializers.ValidationError("保存失败")
        else:

            # 3,返回响应,
            transaction.savepoint_commit(sid)  # TODO 提交
            return SKU.objects.get(id=instance.id)


# 2,sku商品分类序列化器
class SKUCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = ("id", "name")


# 3,sku简要信息序列化器
class SKUGoodSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = ("id", "name")


# 商品规格的选项
class SpecificationOptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = ('id', 'value')


# 4.sku的商品规格序列化器
class SKUGoodsSpecsSerializer(serializers.ModelSerializer):
    # 1,重写spu(如果不重写，spu会转换成整数，需要以字符串，不管多方一方read_only要写)
    spu = serializers.StringRelatedField(read_only=True)  # id的中文名字
    spu_id = serializers.IntegerField()  # spu_id

    # 2,重写option
    options = SpecificationOptionSerializer(read_only=True, many=True)  # related_name= 多方的别名是给当一对多时,给一方查询时候使用

    class Meta:
        model = SPUSpecification
        fields = '__all__'
